package com.duo.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.duo.constant.GlobalConstant;
import com.duo.dto.UserLoginDTO;
import com.duo.dto.WXLoginBackInfo;
import com.duo.entity.User;
import com.duo.exception.BaseException;
import com.duo.mapper.UserMapper;
import com.duo.properties.WeChatProperties;
import com.duo.service.UserService;
import com.duo.utils.HttpClientUtil;
import com.duo.utils.JwtUtil;
import com.duo.utils.Md5Utils;
import com.duo.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @Author: Xrx
 * @Description:
 * @CreateTime: 2023/7/10 15:17
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    // 微信服务接口地址
    public static final String WX_LOGIN_PATH = "https://api.weixin.qq.com/sns/jscode2session";

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private WeChatProperties weChatProperties;

    @Autowired
    private RedisUtils redisUtils;


    /**
     * 微信登录
     * @return
     */
    @Override
    public Object wxLogin(UserLoginDTO code, String oldToken) {
        // 如果缓存不为空，删除缓存的token
        if (JwtUtil.isExpiration(oldToken)) {
            oldToken = JwtUtil.getToken(oldToken);
            if (!Objects.isNull(redisUtils.getCacheObject(GlobalConstant.TOKEN_PREFIX + oldToken))) {
                redisUtils.deleteObject(GlobalConstant.TOKEN_PREFIX + oldToken);
            }
        }

        String openid = getOpenid(code.getCode());
        // 判断openid是否为空，如果为空表示登录失败，抛出业务异常
        if (StrUtil.isBlank(openid)) {
            throw new BaseException("登录异常");
        }
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getOpenid, openid);
        User user = this.getOne(wrapper);
        // 如果是新用户，自动完成注册
        if (ObjectUtil.isNull(user)) {
            user = new User();
            user.setOpenid(openid);
            userMapper.insert(user);
        }
        // 生成token
        String token = Md5Utils.getMd5(openid);
        user = userMapper.selectOne(wrapper);
        redisUtils.setCacheObject(GlobalConstant.TOKEN_PREFIX + token, user, GlobalConstant.TIME, TimeUnit.MINUTES);
        HashMap<String, String> map = new HashMap<>();
        token = JwtUtil.getJwt(token);
        map.put("token", token);
        log.info("用户登陆成功, openid: {}", openid);
        return map;
    }

    /**
     * 调用微信接口服务，获取微信用户的openid
     * @param code
     * @return
     */
    private String getOpenid(String code) {
        HashMap<String, String> map = new HashMap<>();
        map.put("appid", weChatProperties.getAppid());
        map.put("secret", weChatProperties.getSecret());
        map.put("js_code", code);
        map.put("grant_type", "authorization_code");
        String json = HttpClientUtil.doGet(WX_LOGIN_PATH, map);
        WXLoginBackInfo jsonObject = JSONObject.parseObject(json, WXLoginBackInfo.class);
        return jsonObject.getOpenid();
    }


}
